package com.yuzhi.master.drainEvents.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuzhi.common.contant.Constants;
import com.yuzhi.common.contant.EventsStatusConstant;
import com.yuzhi.common.core.domain.PageQuery;
import com.yuzhi.common.core.page.PageDataInfo;
import com.yuzhi.common.exception.base.BaseException;
import com.yuzhi.common.helper.LoginHelper;
import com.yuzhi.common.util.StringUtils;
import com.yuzhi.common.util.redis.CacheUtils;
import com.yuzhi.master.drainEvents.domain.bo.DrainEventDispatch;
import com.yuzhi.master.drainEvents.domain.bo.DrainEvents;
import com.yuzhi.master.drainEvents.domain.bo.DrainEventsBo;
import com.yuzhi.master.drainEvents.domain.bo.DrainMaintOrders;
import com.yuzhi.master.drainEvents.domain.request.DrainEventDispatchReq;
import com.yuzhi.master.drainEvents.domain.request.DrainEventsReq;
import com.yuzhi.master.drainEvents.domain.request.DrainMaintOrdersReq;
import com.yuzhi.master.drainEvents.domain.vo.*;
import com.yuzhi.master.drainEvents.mapper.DrainEventDispatchMapper;
import com.yuzhi.master.drainEvents.mapper.DrainEventsMapper;
import com.yuzhi.master.drainEvents.mapper.DrainMaintOrdersMapper;
import com.yuzhi.master.drainEvents.service.IDrainEventsService;
import com.yuzhi.master.drainMsgNotice.service.IDrainMsgNoticeService;
import com.yuzhi.master.sewage.device.domain.DrainDevice;
import com.yuzhi.master.sewage.device.mapper.DrainDeviceMapper;
import com.yuzhi.system.service.impl.SysUserServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 事件表业务实现层
 *
 * @Author mr.lcc
 * @Data 2025/7/24 12:40
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IDrainEventsServiceImpl extends ServiceImpl<DrainEventsMapper, DrainEvents> implements IDrainEventsService {

    private final DrainEventsMapper drainEventsMapper;


    private final DrainEventDispatchMapper drainEventDispatchMapper;

    private final DrainMaintOrdersMapper drainMaintOrdersMapper;

    private final DrainDeviceMapper drainDeviceMapper;

    private final IDrainMsgNoticeService drainMsgNoticeService;

    private final SysUserServiceImpl userService;

    /**
     * 根据用户ID获取部门ID
     *
     * @param userId 用户ID
     * @return 部门ID
     */
    public String getDeptId(String userId) {
        return drainDeviceMapper.getDeptIdByUserId(userId);
    }


    /**
     * 公共条件构建
     */
    private QueryWrapper<DrainEvents> buildBaseWrapper(DrainEventsReq request) {
        QueryWrapper<DrainEvents> wrapper = Wrappers.query();
        wrapper.eq("de.deleted", Constants.UNDELETED);

        if (StringUtils.isNotBlank(request.getSourceType())) {
            wrapper.eq("de.source_type", request.getSourceType());
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            wrapper.between("de.reported_at", request.getStartTime(), request.getEndTime());
        }
        if (StringUtils.isNotBlank(request.getSiteType())) {
            wrapper.eq("de.site_type", request.getSiteType());
        }
        if (StringUtils.isNotBlank(request.getSiteName())) {
            wrapper.eq("de.site_name", request.getSiteName());
        }
        if (StringUtils.isNotBlank(request.getQuestionDevice())) {
            wrapper.eq("de.question_device", request.getQuestionDevice());
        }

        wrapper.orderByDesc("de.reported_at").orderByAsc("de.events_status");
        return wrapper;
    }

    /**
     * 事件查询（status_type=1）
     */
    private Wrapper<DrainEvents> buildQueryWrapper(DrainEventsReq request) {
        QueryWrapper<DrainEvents> wrapper = buildBaseWrapper(request);
        wrapper.eq("de.status_type", 1);
        return wrapper;
    }

    /**
     * 工单查询（status_type=2，支持 processor 条件）
     */
    private Wrapper<DrainEvents> buildQueryWrapper2(DrainEventsReq request) {
        QueryWrapper<DrainEvents> wrapper = buildBaseWrapper(request);
        wrapper.eq("de.status_type", 2);

        if (StringUtils.isNotBlank(request.getProcessName())) {
            wrapper.eq("ded.processor_id", request.getProcessName());
        }
        return wrapper;
    }

    /**
     * 设备名称映射
     */
    private Map<String, String> buildDeviceNameMap(List<DrainEventsVo> records) {
        Set<String> ids = records.stream().map(DrainEventsVo::getSource).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
        if (ids.isEmpty()) return Collections.emptyMap();

        LambdaQueryWrapper<DrainDevice> wrp = new LambdaQueryWrapper<>();
        wrp.eq(DrainDevice::getDeleted, Constants.UNDELETED).in(DrainDevice::getDeviceId, ids);

        return drainDeviceMapper.selectList(wrp).stream().collect(Collectors.toMap(DrainDevice::getDeviceId, DrainDevice::getDeviceName, (a, b) -> b));
    }



    /**
     * 批量查询 factoryName
     */
    private Map<String, String> buildFactoryNameMap(List<DrainEventsVo> records) {
        Set<String> keys = records.stream().filter(r -> StringUtils.isNotBlank(r.getSiteType()) && StringUtils.isNotBlank(r.getSiteName()) && r.getSiteType().matches("[1-4]")).map(DrainEventsVo::getSiteName).collect(Collectors.toSet());

        if (keys.isEmpty()) return Collections.emptyMap();

        return drainDeviceMapper.batchGetFactoryNames(keys).stream().collect(Collectors.toMap(m -> String.valueOf(m.get("id")), m -> String.valueOf(m.get("fact_name")), (a, b) -> b));
    }


    /**
     * 获取数据字典
     */
    @Override
    public List<DataDictionary> getDataDictionary(Integer type) {
        final String dictType = "events_source";
        List<DataDictionary> dictionaryList = drainEventsMapper.getDataDictionary(dictType);

        // 默认或 type=1：过滤掉停用项
        if (type == null || type == 1) {
            Set<String> excludedValues = Set.of("3");
            return dictionaryList.stream().filter(item -> !excludedValues.contains(item.getDictValue())).collect(Collectors.toList());
        }

        // type=2：可根据需求控制允许项（此处仍排除 3）
        if (type == 2) {
            Set<String> excludedValues = Set.of("3");
            return dictionaryList.stream().filter(item -> !excludedValues.contains(item.getDictValue())).collect(Collectors.toList());
        }

        return dictionaryList;
    }


    /**
     * 新增
     *
     * @param bo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(DrainEventsBo bo) {

        DrainEvents dto = BeanUtil.toBean(bo, DrainEvents.class);
        // 1.新增drain_events事件表数据
        // 设置上报时间为上传时间
        // 设置上报人id为当前登录用户如 "sys_user:1" 结果是 "1"
        String loginId = StpUtil.getLoginIdAsString();
        String userId = StrUtil.subAfter(loginId, ":", true);

        // 设置当前新建事件表的时间状态默认为events_status=1 (待处理) 当前状态（关联数据字典，如未处理，已派发、结案等）
        dto.setEventsStatus("1");
        dto.setReporterId(userId);

        // 默认给默认值status_type 上报类型（1=事件上报、2=工单上报、默认状态为1）
        if (dto.getStatusType() == null) {
            dto.setStatusType(1);
        }

        // 在新增数据时，设置admacd部门ID为当前新增人员的部门ID
        String deptId = getDeptId(userId);
        if (StringUtils.isNotBlank(deptId)) {
            dto.setAdmacd(deptId);
        } else {
            log.warn("用户（userId={}）的部门ID为空，尝试使用管理员部门ID", userId);
            // 默认给默认值admacd部门ID为管理员数据权限
            String adminDept = getDeptId("1");
            dto.setAdmacd(adminDept);
            log.error("管理员（userId=1）的部门ID为空，已使用默认根部门ID：{}", adminDept);
        }

        boolean flag = drainEventsMapper.insert(dto) > 0;

        // 2.在drain_event_dispatch表中新增记录
        // 新增事件表的时候drain_events的时候，在往事件派发表drain_evcent_dispatch表中新增一条数据，这个数据默认处置人员是上报人员自己。
        DrainEventDispatch dispatch = new DrainEventDispatch();
        // 关联事件id
        dispatch.setEventId(dto.getId());
        // 事件派发人员的唯一标识（默认为当前登录操作用户）
        dispatch.setDispatcherId(userId);
        // 事件接受人员的唯一标识（默认为当前登录操作用户）
        dispatch.setReceiverId(userId);
        // 实际处置人员的唯一标识（默认为当前登录操作用户）
        //dispatch.setProcessorId(userId);
        // 行为类型默认为1派发中（关联behavior_type数据字典，如1(派发)、2(接收)、3(处理)、4(转派)、5(关闭-暂时没用到)
        dispatch.setActionType("1");
        // 行为时间为当前系统新增时间
        dispatch.setActionTime(LocalDateTime.now());

        boolean flag2 = drainEventDispatchMapper.insert(dispatch) > 0;
        if (!flag2) {
            log.error("新增事件派发信息失败，数据：{}", dispatch);
            return false;
        }

        // 3.响应是否成功
        return flag;
    }

    /**
     * 编辑工单
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean edit2(DrainEventsBo dto) {
        // 1. 工单管理编辑更新
        DrainEvents drainEvents = drainEventsMapper.selectById(dto.getId());
        if (drainEvents == null) {
            log.error("工单不存在，ID: {}", dto.getId());
            return false;
        }

        // 2. 判断是否为工单上报类型
        if (!Integer.valueOf(2).equals(drainEvents.getStatusType())) {
            log.error("工单状态类型不正确，ID: {}，statusType: {}", dto.getId(), drainEvents.getStatusType());
            return false;
        }

        // 3. 更新事件表
        DrainEvents events = BeanUtil.toBean(dto, drainEvents.getClass());
        // 设置执行人和执行时间
        events.setProcessTime(dto.getProcessTime());
        // 更新目前先变成处理中
        events.setEventsStatus("2");

        boolean flag = drainEventsMapper.updateById(events) > 0;
        if (!flag) {
            log.error("工单管理更新失败，数据：{}", events);
            return false;
        }

        // 4. 更新事件表关联表
        DrainEventDispatch dispatch = new DrainEventDispatch();
        // 实际处置人员的唯一标识人员id
        dispatch.setProcessorId(dto.getProcessorId());

        LambdaUpdateWrapper<DrainEventDispatch> wrp = new LambdaUpdateWrapper<>();
        // 更新条件
        wrp.eq(DrainEventDispatch::getEventId, drainEvents.getId());
        wrp.eq(DrainEventDispatch::getDeleted, Constants.UNDELETED);

        flag = drainEventDispatchMapper.update(dispatch, wrp) > 0;
        if (!flag) {
            log.error("工单管理关联表更新失败，数据：{}", dispatch);
            throw new BaseException("工单管理关联表更新失败");
        }

        return true;
    }



    /**
     * 事件分派操作 - 处理事件派发/处置详情
     *
     * @param dto 派发请求参数
     * @return true 表示派发成功，false 表示派发失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean handOut(DrainEventDispatchReq dto) {

        return true;
    }

    /**
     * 工单分派操作 - 处理事件派发/处置详情
     *
     * @param dto 派发请求参数
     * @return true 表示派发成功，false 表示派发失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean handOut2(DrainEventDispatchReq dto) {
        // 1. 根据事件ID查询已存在的事件派发/处置详情记录
        LambdaQueryWrapper<DrainEventDispatch> qw = new LambdaQueryWrapper<>();
        qw.eq(DrainEventDispatch::getEventId, dto.getEventId());
        qw.eq(DrainEventDispatch::getDeleted, Constants.UNDELETED);
        DrainEventDispatch dispatchRecord = drainEventDispatchMapper.selectOne(qw);

        if (ObjectUtil.isEmpty(dispatchRecord)) {
            log.error("事件派发记录未找到，eventId={}", dto.getEventId());
            return false;
        }

        // 2. 设置字段值
        // 2.1 设置当前登录用户为派发人
        String loginId = StpUtil.getLoginIdAsString();
        String sysUserId = StrUtil.subAfter(loginId, ":", true);
        dispatchRecord.setDispatcherId(sysUserId);

        // 2.2 设置接收人（工单执行人）
        dispatchRecord.setReceiverId(dto.getReceiverId());

        // 2.3 实际处置人为接收人
        dispatchRecord.setProcessorId(dto.getReceiverId());

        // 2.4 设置行为类型为“转派”（4）
        dispatchRecord.setActionType("4");

        // 2.5 设置操作时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
        LocalDateTime actionTime = LocalDateTime.parse(dto.getActionTime(), formatter);
        dispatchRecord.setActionTime(actionTime);

        // 2.6 设置更新时间
        dispatchRecord.setUpdateTime(LocalDateTime.now());

        // 3. 更新事件派发记录
        boolean updatedDispatch = drainEventDispatchMapper.updateById(dispatchRecord) > 0;
        if (!updatedDispatch) {
            log.error("更新事件派发记录失败，eventId={}", dto.getEventId());
            return false;
        }

        // 4. 更新事件状态
        String eventId = dispatchRecord.getEventId();
        DrainEvents eventRecord = drainEventsMapper.selectById(eventId);

        // -----新添加的逻辑-----
        // 在新增数据时，设置admacd部门ID为 当前事件接收人员的唯一标识 的部门ID
        String deptId = getDeptId(dto.getReceiverId());
        if (StringUtils.isNotBlank(deptId)) {
            eventRecord.setAdmacd(deptId);
        } else {
            log.warn("用户（userId={}）的部门ID为空，尝试使用管理员部门ID", deptId);
            // 默认给默认值admacd部门ID为管理员数据权限
            String adminDept = getDeptId("1");
            eventRecord.setAdmacd(adminDept);
            log.error("管理员（userId=1）的部门ID为空，已使用默认根部门ID：{}", adminDept);
        }

        if (ObjectUtil.isEmpty(eventRecord)) {
            log.error("事件记录未找到，eventId={}", eventId);
            return false;
        }

        // 仅当事件状态不为“已关闭”(5)时，才可更新状态
        if (!"5".equals(eventRecord.getEventsStatus())) {
            // 设置事件处理状态为“处理中”(2) TODO 转工单状态类型逻辑需要根据业务需求来改编
            //eventRecord.setEventsStatus("2");

            boolean updatedEvent = drainEventsMapper.updateById(eventRecord) > 0;
            if (!updatedEvent) {
                log.error("更新事件状态失败，eventId={}", eventId);
                return false;
            }
        }

        return true;
    }


    /**
     * 转维修单
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean maintain(DrainMaintOrdersReq dto) {
        // 注：转维修单的时候关联事件表id和事件派发表的id

        // 1.查询已有的事件派发/处置详情表数据根据事件表数据
        LambdaQueryWrapper<DrainEventDispatch> qw = new LambdaQueryWrapper<>();
        qw.eq(DrainEventDispatch::getEventId, dto.getEventId());
        qw.eq(DrainEventDispatch::getDeleted, Constants.UNDELETED);
        DrainEventDispatch drainEventDispatch = drainEventDispatchMapper.selectOne(qw);

        // 2.设置数据值
        // 设置事件派发处置id dispatch_id
        dto.setDispatchId(drainEventDispatch.getId());
        // 填单人员默认为系统登录用户 creator_id
        String loginId = StpUtil.getLoginIdAsString();
        String sysUserId = StrUtil.subAfter(loginId, ":", true);
        dto.setCreatorId(sysUserId);
        // 维修单编号、保修时间、维修单位、故障情况描述、维修措施、维修时间、维修费用、系统记录穿件时间、维修站点ID、维修站点类型。暂时未处理

        // 3.设置事件表状态为已分派
        String eventId = drainEventDispatch.getEventId();
        DrainEvents drainEvents = drainEventsMapper.selectById(eventId);
        if (ObjectUtil.isEmpty(drainEvents)) {
            log.error("未查询到事件表数据！");
            return false;
        }
        // 只有状态为派发或者待处理中时，才能进行分派。1(派发)、2(接收)、3(处理)、4(转派)、5(关闭)
        if (!drainEvents.getEventsStatus().equals("5")) {
            // 事件处理状态 1待处理 2处理中 3已解决 4已关闭
            drainEvents.setEventsStatus("2");
            boolean flagDrainEvents = drainEventsMapper.updateById(drainEvents) > 0;
            if (!flagDrainEvents) {
                log.error("更新事件表数据状态失败！");
                return false;
            }
        }

        // 4.新增数据
        DrainMaintOrders bean = BeanUtil.toBean(dto, DrainMaintOrders.class);
        // 默认为系统当前时间，待优化。
        bean.setReportTime(LocalDateTime.now());
        // 设置站点类型
        bean.setSiteType(drainEvents.getSiteType());
        // 设置具体站点（例如：白塔污水厂）
        bean.setSiteId(drainEvents.getSiteId());
        // 设置维修费用默认为0
        bean.setCost(BigDecimal.ZERO);
        // 故障情况描述
        bean.setFaultDescription(drainEvents.getDescription());
        // 设置默认为外部维修
        bean.setOrderType("2");

        // 5.订单编号生成规则：P202507250001
        // === 生成维修单编号（每天从0001开始） ===
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        //序列号(每天从1自增的四位序列号)
        String seq = CacheUtils.getDailyIncrementalSequence();
        // 格式化维修单号：P202508020001
        String orderNo = String.format("P%s%s", dateStr, seq);
        bean.setOrderNumber(orderNo);

        // 6.新增
        boolean flag = drainMaintOrdersMapper.insert(bean) > 0;
        if (!flag) {
            log.error("新增维修单失败！");
            return false;
        }
        return flag;
    }

    /**
     * 结案
     *
     * @param list
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean finish(List<String> list) {
        // 1.根据传入的主键id查询事件数据
        List<DrainEvents> drainEvents = drainEventsMapper.selectBatchIds(list);
        if (ObjectUtil.isEmpty(drainEvents)) {
            log.error("未查询到事件表数据！");
            return false;
        }

        for (DrainEvents drainEvent : drainEvents) {
            // 批量设置事件表状态为已解决。1(派发)、2(接收)、3(处理)、4(转派)、5(关闭)
            drainEvent.setEventsStatus("3");
            // 设置处理时间为当前系统结案时间
            drainEvent.setProcessTime(LocalDateTime.now());
            // 设置更新人为当前登录用户id
            String loginId = StpUtil.getLoginIdAsString();
            String sysUserId = StrUtil.subAfter(loginId, ":", true);
            drainEvent.setUpdater(sysUserId);
        }

        // 2.批量更新事件表数据
        boolean updateBatchById = drainEventsMapper.updateBatchById(drainEvents);
        if (!updateBatchById) {
            log.error("批量更新事件表数据失败！");
            return false;
        }
        return updateBatchById;
    }

    /**
     * 完结
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean completion(DrainEventsReq dto) {
        // 1.根据传入的主键id查询事件数据
        DrainEvents drainEvents = drainEventsMapper.selectById(dto.getId());
        if (ObjectUtil.isEmpty(drainEvents)) {
            log.error("未查询到事件表数据！id: {}", dto.getId());
            return false;
        }

        // 2.判断事件处理状态是否为处理中(状态"3") 3已解决
        if (!"3".equals(drainEvents.getEventsStatus())) {
            log.warn("事件状态不是已解决，无需更新！当前状态: {}", drainEvents.getEventsStatus());
            return false;
        }

        // 3.设置事件表状态为已解决(状态"4") 4已经关闭
        drainEvents.setEventsStatus("4");

        // 4.更新数据库
        int rows = drainEventsMapper.updateById(drainEvents);
        if (rows <= 0) {
            log.error("更新事件表数据状态失败！id: {}", dto.getId());
            return false;
        }
        return true;
    }

    /**
     * 设备类型选择，根据备注分类进行查询。
     *
     * @param remark
     * @return
     */
    @Override
    public List<DictItemDevice> getDeviceTypeByRemark(String remark) {
        List<DictItemDevice> dictItemDevices = drainEventsMapper.getDeviceTypeByRemark(remark);
        return dictItemDevices;
    }

    /**
     * 复制新增接口
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public DrainEventsVo getOneAdd(String id) {
        DrainEventsVo one = drainEventsMapper.getOneAdd(id);
        // 设置状态为未处理状态
        one.setEventsStatus("1");
        return one;
    }


    /**
     * 移动端我的工单任务列表
     *
     * @param eventsStatus 1:待办工单 5：催办工单
     * @return 最新一条
     */
    @Override
    public DrainEventsResult queryAppTodoEvents(String eventsStatus) {
        DrainEventsResult result = new DrainEventsResult();

        //状态 1(待处理)、2(处理中)、3(已解决)4(已关闭)
        Map<String, String> statusMap = new HashMap<>();
        statusMap.put("1", "待处理");
        statusMap.put("2", "处理中");
        statusMap.put("3", "已解决");
        statusMap.put("4", "已关闭");

        //获取当前登录的用户ID
        String userId = LoginHelper.getUserId();

        //查询移动端我的待办工单(按照部门权限过滤)
        DrainEventsReq request = new DrainEventsReq();
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(1);
        pageQuery.setPageSize(10);

        //eventsStatus传空 默认查询工单,为5查询催办任务
        request.setEventsStatus(eventsStatus);
        request.setPageQuery(pageQuery);

        PageDataInfo dataInfo = queryAppMoreOrders(request);
        List<DrainEventsVo> voList = dataInfo.getList();

        if (voList != null && !voList.isEmpty()) {
            result.setCount(voList.size());

            DrainEventsVo eventsVo = voList.get(0);

            DrainEventsResultVo vo = BeanUtil.toBean(eventsVo, DrainEventsResultVo.class);

            if (vo.getActionTime() != null) {
                // 获取当前时间
                LocalDateTime now = LocalDateTime.now();
                // 计算时间差
                Duration duration = Duration.between(vo.getActionTime(), now);
                long hours = duration.toHours();

                vo.setTimeout(hours);
            }

            //状态转义
            vo.setEventsStatus(statusMap.getOrDefault(vo.getEventsStatus(), ""));

            result.setEventsResultVo(vo);
        }

        return result;
    }


    /**
     * 移动端工单详情
     * 后端提供待处理和处理中的状态值的工单
     *
     * @param request@return
     */
    @Override
    public PageDataInfo queryAppMoreOrders(DrainEventsReq request) {
        return PageDataInfo.build();
    }

    /**
     * 构建工单查询条件
     *
     * @param request
     * @return
     */
    private Wrapper<DrainEvents> buildQueryWrapper3(DrainEventsReq request) {
        Map<String, Object> params = request.getParams();
        QueryWrapper<DrainEvents> wrapper = Wrappers.query();
        // 1.默认查询条件：未删除
        wrapper.eq("de.deleted", Constants.UNDELETED);
        // 2.查询工单信息，通过statusType=2状态区分
        wrapper.eq("de.status_type", 2);

        String eventsStatus = request.getEventsStatus();

        if (StringUtils.isBlank(eventsStatus)) {
            // 状态为空，查询待处理和处理中状态的工单
            wrapper.in("de.events_status", EventsStatusConstant.TO_BE_PROCESSED, EventsStatusConstant.BEING_PROCESSED);
        } else {
            switch (eventsStatus) {
                case "5":
                    // 催办工单
                    wrapper.eq("de.events_status", EventsStatusConstant.REMIND_HANDLING);
                    break;
                // 如果后续有其他状态，可以继续加 case
                default:
                    // 可根据需求处理其他情况，或者不处理
                    break;
            }
        }

        //排序
        wrapper.orderByDesc("ded.action_time");

        return wrapper;
    }

    /**
     * 工单统计
     *
     * @return
     */
    @Override
    // 在 service 中处理
    public List<DrainWorkOrderStatisticVo> queryAppWorkOrderStatistics(DrainEventsReq req) {
        // 如果 endTime 存在，设置为当天最后一秒
        if (req.getEndTime() != null) {
            LocalDateTime endOfDay = req.getEndTime().withHour(23).withMinute(59).withSecond(59);
            req.setEndTime(endOfDay);
        }

        List<DrainWorkOrderStatisticVo> result = drainEventsMapper.queryAppWorkOrderStatistics(req);

        if (ObjectUtil.isEmpty(result)) {
            log.error("查询工单统计结果为空");
            return Collections.emptyList();
        }
        return result;
    }

    /**
     * 人工处理工单统计接口
     *
     * @return
     */
    @Override
    public List<DrainWorkOrderHandlingVo> queryAppWorkOrderHandlingStatistics(DrainEventsReq req) {
        // 如果 endTime 存在，设置为当天最后一秒
        if (req.getEndTime() != null) {
            LocalDateTime endOfDay = req.getEndTime().withHour(23).withMinute(59).withSecond(59);
            req.setEndTime(endOfDay);
        }
        List<DrainWorkOrderHandlingVo> result = drainEventsMapper.queryAppWorkOrderHandlingStatistics(req);
        if (ObjectUtil.isEmpty(result)) {
            log.error("查询工单统计结果为空");
            return Collections.emptyList();
        }
        return result;
    }

    /**
     * 工单处理统计接口
     *
     * @return
     */
    @Override
    public WorkOrderHandlingEChartsVo queryAppWorkOrderHandlingStatisticsForECharts(DrainEventsReq req) {
        // 获取工单处理统计数据原始接口增强返回前端需要的数据接口
        List<DrainWorkOrderHandlingVo> result = queryAppWorkOrderHandlingStatistics(req);

        WorkOrderHandlingEChartsVo vo = new WorkOrderHandlingEChartsVo();
        List<String> names = new ArrayList<>();
        List<Long> totals = new ArrayList<>();
        List<Long> completed = new ArrayList<>();

        for (DrainWorkOrderHandlingVo item : result) {
            names.add(item.getProcessorName());
            totals.add(item.getTotalWorkOrders());
            completed.add(item.getCompletedWorkOrders());
        }

        vo.setProcessorNames(names);
        vo.setTotalOrders(totals);
        vo.setCompletedOrders(completed);

        return vo;
    }
}
